package com.quxing.amazon.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.quxing.amazon.common.ResponseUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static com.quxing.amazon.common.StatusConst.*;

/**
 * @author zhb
 * @description 自定义认证过滤器
 * @date 2020/11/27 16:48
 */
@SuppressWarnings("Duplicates")
@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final JwtUtil jwtUtil;

    @Override
    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取请求中的用户名和密码
        String username, password;
        LoginForm loginData;
        try {
            loginData = new ObjectMapper().readValue(request.getInputStream(), LoginForm.class);
        } catch (IOException e) {
            throw new AuthException("用户名或密码未获取到！");
        }
        username = loginData.getUsername();
        password = loginData.getPassword();

        if (username == null) {
            username = "";
        }
        if (password == null) {
            password = "";
        }
        username = username.trim();
        //创建一个未认证的token
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
        return super.getAuthenticationManager().authenticate(token);

    }

    /**
     * 认证成功逻辑
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        try {
            String jwt = jwtUtil.createJwt(authResult);
            ResponseUtil.writeSuccess(response, LOGIN_SUCCESS, jwt);
        } catch (Exception e) {
            log.error("创建token失败:{}", e.getMessage());
            ResponseUtil.writeError(response, ERROR);
        }
    }

    /**
     * 认证失败逻辑
     *
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        if (failed instanceof BadCredentialsException) {
            ResponseUtil.writeError(response, USERNAME_PASSWORD_ERROR);
        } else if (failed instanceof DisabledException) {
            ResponseUtil.writeError(response, USER_DISABLED);
        } else if (failed instanceof AuthException) {
            ResponseUtil.writeError(response, failed.getMessage());
        } else {
            log.error("认证失败异常:{}", failed.getMessage());
            ResponseUtil.writeError(response, ERROR);
        }
    }
}
